﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Drawing;

namespace Noris.Tools.SystemResourceMonitor.UI
{
    #region class HotButton 
    public class HotButton : Button
    {
        public HotButton()
        {
            this.FlatStyle = System.Windows.Forms.FlatStyle.Flat;
            this.FlatAppearance.BorderSize = 0;
            this.FlatAppearance.CheckedBackColor = Color.Transparent;
            this.FlatAppearance.MouseOverBackColor = Color.Transparent;
            this.FlatAppearance.MouseDownBackColor = Color.Transparent;
            this.Text = "";

            this.MouseEnter += new EventHandler(HotButton_MouseEnter);
            this.MouseLeave += new EventHandler(HotButton_MouseLeave);
            this.MouseDown += new MouseEventHandler(HotButton_MouseDown);
            this.MouseUp += new MouseEventHandler(HotButton_MouseUp);

            this._CurrentImageForState = _ImageState.None;
        }
        void HotButton_MouseUp(object sender, MouseEventArgs e)
        {
            this._IsPressed = false;
            this._RefreshImage();
        }
        void HotButton_MouseDown(object sender, MouseEventArgs e)
        {
            this._IsPressed = true;
            this._RefreshImage();
        }
        void HotButton_MouseLeave(object sender, EventArgs e)
        {
            this._OnMouse = false;
            this._RefreshImage();
        }
        void HotButton_MouseEnter(object sender, EventArgs e)
        {
            this._OnMouse = true;
            this._RefreshImage();
        }
        public Image ImageFalseNormal { get { return this._ImageFalseNormal; } set { this._ImageFalseNormal = value; this._RefreshImage(); } }
        public Image ImageFalseHot { get { return this._ImageFalseHot; } set { this._ImageFalseHot = value; this._RefreshImage(); } }
        public Image ImageFalsePressed { get { return this._ImageFalsePressed; } set { this._ImageFalsePressed = value; this._RefreshImage(); } }
        public Image ImageTrueNormal { get { return this._ImageTrueNormal; } set { this._ImageTrueNormal = value; this._RefreshImage(); } }
        public Image ImageTrueHot { get { return this._ImageTrueHot; } set { this._ImageTrueHot = value; this._RefreshImage(); } }
        public Image ImageTruePressed { get { return this._ImageTruePressed; } set { this._ImageTruePressed = value; this._RefreshImage(); } }

        public bool Value { get { return this._Value; } set { this._Value = value; this._RefreshImage(); } }

        private Image _ImageFalseNormal;
        private Image _ImageFalseHot;
        private Image _ImageFalsePressed;
        private Image _ImageTrueNormal;
        private Image _ImageTrueHot;
        private Image _ImageTruePressed;

        private _ImageState _CurrentImageForState;
        private bool _OnMouse;
        private bool _IsPressed;
        private bool _Value;

        private void _RefreshImage()
        {
            _ImageState state = _GetCurrentState();
            if (state != _CurrentImageForState)
            {
                Image image = _GetImageForState(state);
                this.Image = image;
                if (image == null)
                    _CurrentImageForState = _ImageState.None;
                else
                    _CurrentImageForState = state;
            }
        }
        private _ImageState _GetCurrentState()
        {
            if (this._Value)
            {
                if (this._IsPressed) return _ImageState.TruePressed;
                if (this._OnMouse) return _ImageState.TrueHot;
                return _ImageState.TrueNormal;
            }
            else
            {
                if (this._IsPressed) return _ImageState.FalsePressed;
                if (this._OnMouse) return _ImageState.FalseHot;
                return _ImageState.FalseNormal;
            }
        }
        private Image _GetImageForState(_ImageState state)
        {
            switch (state)
            {
                case _ImageState.FalseNormal: return this._ImageFalseNormal;
                case _ImageState.FalseHot: return this._ImageFalseHot;
                case _ImageState.FalsePressed: return this._ImageFalsePressed;
                case _ImageState.TrueNormal: return this._ImageTrueNormal;
                case _ImageState.TrueHot: return this._ImageTrueHot;
                case _ImageState.TruePressed: return this._ImageTruePressed;
            }
            return null;
        }
        protected override void OnPaint(PaintEventArgs e)
        {
            e.Graphics.Clear(this.BackColor);
            // e.Graphics.Clear(Color.Transparent);
            if (this.Image != null)
            {
                Point center = new Point(this.ClientRectangle.X + this.ClientRectangle.Width / 2, this.ClientRectangle.Y + this.ClientRectangle.Height / 2);
                Size imgSize = this.Image.Size;
                Rectangle imgArea = new Rectangle(center.X - imgSize.Width / 2, center.Y - imgSize.Height / 2, imgSize.Width, imgSize.Height);

                e.Graphics.DrawImage(this.Image, imgArea);
            }
        }
        private enum _ImageState { None, FalseNormal, FalseHot, FalsePressed, TrueNormal, TrueHot, TruePressed }
    }
    #endregion
    #region FormMoveSupport
    /// <summary>
    /// Třída, která podporuje přesouvání formuláře za jeho tělo (a za jeho zvolené controly), nejen za titulek.
    /// Je tak možno přesouvat i formulář bez borderu.
    /// Použití: na formuláři se vytvoří instanční proměnná typu FormMoveSupport, do konstruktoru se předá hostitelský form.
    /// Tím se form (jeho vlastní plocha) stane přesouvatelná.
    /// Následně je možno zaregistrovat libovolný další control (metodou this.RegisterControl(control)),
    /// který se pak rovněž stane aktivním z hlediska přesouvání.
    /// </summary>
    public class FormMoveSupport
    {
        #region Public vrstva
        /// <summary>
        /// Konstruktor, předává se Form který se bude přesouvat.
        /// </summary>
        /// <param name="form"></param>
        public FormMoveSupport(Form form)
        {
            this._Form = form;
            this.RegisterControl(form);
        }
        /// <summary>
        /// Registrace libovolného controlu.
        /// This se zaháčkuje do jeho Mouse eventů a ošetří je tak, aby bylo možno jejich přesouváním přesouvat Form.
        /// </summary>
        /// <param name="control"></param>
        public void RegisterControl(Control control)
        {
            control.MouseDown += new MouseEventHandler(_MouseDown);
            control.MouseMove += new MouseEventHandler(_MouseMove);
            control.MouseUp += new MouseEventHandler(_MouseUp);
        }
        #endregion
        #region Privátní vrstva
        void _MouseDown(object sender, MouseEventArgs e)
        {
            if (e.Button != MouseButtons.Left) return;

            Point fp = this._Form.Location;
            Point mp = Control.MousePosition;
            Point df = new Point(mp.X - fp.X, mp.Y - fp.Y);
            this._FormToMouseOffset = df;

            Size ds = SystemInformation.DragSize;
            this._InactiveMouseArea = new Rectangle(mp.X - ds.Width / 2, mp.Y - ds.Height / 2, ds.Width, ds.Height);
        }
        void _MouseMove(object sender, MouseEventArgs e)
        {
            if (!this._FormToMouseOffset.HasValue) return;
            
            Point mp = Control.MousePosition;
            if (this._InactiveMouseArea.HasValue)
            {
                if (this._InactiveMouseArea.Value.Contains(mp)) return;
                this._InactiveMouseArea = null;
            }

            Point df = this._FormToMouseOffset.Value;
            Point fp = new Point(mp.X - df.X, mp.Y - df.Y);
            this._Form.Location = fp;
        }
        void _MouseUp(object sender, MouseEventArgs e)
        {
            this._FormToMouseOffset = null;
        }

        private Form _Form;
        private Point? _FormToMouseOffset;
        private Rectangle? _InactiveMouseArea;
        #endregion
    }
    #endregion
}
